package com.szsh.aiot.hsm.service.impl;

import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.szsh.aiot.common.core.domain.AjaxResult;
import com.szsh.aiot.common.core.domain.RequestDto;
import com.szsh.aiot.common.utils.DateUtils;
import com.szsh.aiot.hsm.dao.HomeNetworkDao;
import com.szsh.aiot.hsm.dao.InfluxDao;
import com.szsh.aiot.hsm.dao.MkDao;
import com.szsh.aiot.hsm.domain.IFlowDevice;
import com.szsh.aiot.hsm.domain.IUserDevice;
import com.szsh.aiot.hsm.domain.homeNetWork.TopoInfo;
import com.szsh.aiot.hsm.enums.DeviceType;
import com.szsh.aiot.hsm.mapper.IFlowDeviceMapper;
import com.szsh.aiot.hsm.mapper.IUserDeviceMapper;
import com.szsh.aiot.hsm.service.DeviceFlowService;
import com.szsh.aiot.hsm.service.UserService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class DeviceFlowServiceImpl implements DeviceFlowService {
    private static final Logger LOGGER = LoggerFactory.getLogger(DeviceFlowServiceImpl.class);

    private final UserService userService;

    private final IFlowDeviceMapper flowDeviceMapper;

    private final IUserDeviceMapper userDeviceMapper;

    private final HomeNetworkDao homeNetworkDao;

    private final MkDao mkDao;

    private final InfluxDao influxDao;

    private final Gson gson;

    public DeviceFlowServiceImpl(UserService userService, IFlowDeviceMapper flowDeviceMapper, IUserDeviceMapper userDeviceMapper, HomeNetworkDao homeNetworkDao, MkDao mkDao, InfluxDao influxDao, Gson gson) {
        this.userService = userService;
        this.flowDeviceMapper = flowDeviceMapper;
        this.userDeviceMapper = userDeviceMapper;
        this.homeNetworkDao = homeNetworkDao;
        this.mkDao = mkDao;
        this.influxDao = influxDao;
        this.gson = gson;
    }

    /**
     * 智能设备流量统计所有设备查询接口
     * @param requestDto 请求参数
     * @return 处理结果
     */
    @Override
    public AjaxResult getAllDeviceList(RequestDto requestDto) {
        // 请求参数
        JsonObject requestJsonObject = requestDto.getRequestJsonElement().getAsJsonObject();

        // 宽带账号
        String broadbandNO = requestJsonObject.get("broadbandNO").getAsString();
        // 网关MAC
        String gatewayMac = requestJsonObject.get("gatewayMac").getAsString();

        // 从数据库中获取数据
        JsonArray returnJsonArray = getDeviceFromDb(broadbandNO);

        // 获取所有的deviceId
        List<Long> deviceIDs = new ArrayList<>();
        returnJsonArray.forEach(jsonElement -> {
            JsonObject jsonObject = jsonElement.getAsJsonObject();
            deviceIDs.add(jsonObject.get("deviceId").getAsLong());
        });

        // 拓扑接口查询设备
        List<TopoInfo> topoDeviceList = homeNetworkDao.getTopoListFromCache(gatewayMac);

        for (TopoInfo topo : topoDeviceList) {
            IUserDevice userDevice = userService.getUserDevice(broadbandNO, topo);
            if (deviceIDs.contains(userDevice.getDeviceID())) {
                continue;
            }

            JsonObject jsonObject = new JsonObject();

            jsonObject.addProperty("deviceId", userDevice.getDeviceID());
            jsonObject.addProperty("deviceName", userDevice.getShowName());
            jsonObject.addProperty("deviceType", DeviceType.getDeviceType(userDevice.getShowName()));

            jsonObject.addProperty("chose", 0);

            returnJsonArray.add(jsonObject);
        }

        return null;
    }

    /**
     * 智能设备流量统计已选择设备查询接口
     * @param requestDto 请求参数
     * @return 处理结果
     */
    @Override
    public AjaxResult getChoseDeviceList(RequestDto requestDto) {
        // 请求参数
        JsonObject requestJsonObject = requestDto.getRequestJsonElement().getAsJsonObject();

        // 宽带账号
        String broadbandNO = requestJsonObject.get("broadbandNO").getAsString();

        return AjaxResult.success(getDeviceFromDb(broadbandNO));
    }

    /**
     * 智能设备流量统计已选择设备保存接口
     * @param requestDto 请求参数
     * @return 处理结果
     */
    @Override
    public AjaxResult saveChoseDeviceList(RequestDto requestDto) {
        // 请求参数
        JsonObject requestJsonObject = requestDto.getRequestJsonElement().getAsJsonObject();

        // 宽带账号
        String broadbandNO = requestJsonObject.get("broadbandNO").getAsString();
        // 设备ID列表
        List<Long> deviceIdList = gson.fromJson(requestJsonObject.get("deviceIdList"), new TypeToken<List<Long>>(){}.getType());

        // 去重
        Set<Long> deviceIdSet = new HashSet<>(deviceIdList);

        // 根据宽带号查出已存在的
        IFlowDevice flowDeviceSearch = new IFlowDevice();
        flowDeviceSearch.setBroadbandNO(broadbandNO);
        List<IFlowDevice> flowDeviceList = flowDeviceMapper.selectIFlowDeviceList(flowDeviceSearch);

        // 需要删除的数据
        List<Long> serNoDeleteList = new ArrayList<>();
        List<Long> deviceIdDeleteList = new ArrayList<>();
        for (IFlowDevice flowDevice : flowDeviceList) {
            if (deviceIdSet.contains(flowDevice.getDeviceId())) {
                // 不需要删除
                // 移除
                deviceIdSet.remove(flowDevice.getDeviceId());
            } else {
                // 需要删除
                serNoDeleteList.add(flowDevice.getSerno());
                deviceIdDeleteList.add(flowDevice.getDeviceId());
            }
        }
        // 需要新增的数据
        List<Long> deviceIdAddList = new ArrayList<>(deviceIdSet);

        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("需要新增数据:{},需要删除数据:{}", deviceIdAddList, deviceIdDeleteList);
        }

        // 1. 通知迈科删除设备mac
        Map<String, String> deleteMap = new HashMap<>();
        for (Long deviceId : deviceIdDeleteList) {
            IUserDevice userDevice = userDeviceMapper.selectIUserDeviceByDeviceID(deviceId);
            if (null == userDevice) {
                continue;
            }
            deleteMap.put(userDevice.getDeviceMac(), mkDao.getType(userDevice));
        }
        if (MapUtils.isEmpty(deleteMap)) {
            if (LOGGER.isWarnEnabled()) {
                LOGGER.warn("无需调用删除");
            }
        } else {
            // 通知删除
            mkDao.batchDeleteReport(deleteMap);
        }

        // 2. 本地删除
        if (CollectionUtils.isNotEmpty(serNoDeleteList)) {
            flowDeviceMapper.deleteIFlowDeviceBySernos(Arrays.toString(serNoDeleteList.toArray(new Long[]{})));
        }
        // 3. 添加
        Map<String, String> addMap = new HashMap<>();
        for (Long deviceId : deviceIdAddList) {
            IUserDevice userDevice = userDeviceMapper.selectIUserDeviceByDeviceID(deviceId);
            String deviceName = userDevice.getShowName();
            String showName = userDevice.getDeviceType() == 1 ? "天翼摄像头" : userDevice.getShowName();

            IFlowDevice flowDevice = new IFlowDevice();
            flowDevice.setBroadbandNO(broadbandNO);
            flowDevice.setDeviceId(deviceId);
            flowDevice.setDeviceType(DeviceType.getDeviceType(showName));
            flowDevice.setDeviceName(deviceName);
            flowDevice.setDeviceMac(userDevice.getDeviceMac());
            flowDevice.setCreateTime(DateUtils.getNowDate());

            addMap.put(userDevice.getDeviceMac(), mkDao.getType(flowDevice, userDevice));

            // 入库
            flowDeviceMapper.insertIFlowDevice(flowDevice);
        }
        if (MapUtils.isEmpty(addMap)) {
            if (LOGGER.isWarnEnabled()) {
                LOGGER.warn("无需调用添加");
            }
        } else {
            // 通知迈科添加设备mac
            mkDao.batchAddReport(addMap);
        }

        return AjaxResult.success();
    }

    /**
     * 智能设备流量统计设备流量获取接口
     * @param requestDto 请求参数
     * @return 处理结果
     */
    @Override
    public AjaxResult pictureData(RequestDto requestDto) {
        // 请求参数
        JsonObject requestJsonObject = requestDto.getRequestJsonElement().getAsJsonObject();

        // 宽带账号
        String broadbandNO = requestJsonObject.get("broadbandNO").getAsString();
        // 设备ID列表
        Long deviceId = requestJsonObject.get("deviceId").getAsLong();
        String deviceIdStr = String.valueOf(deviceId);

        Map<String, Object> returnMap = new HashMap<>();

        returnMap.put("datalist", influxDao.getFlowPushList(deviceIdStr));
        returnMap.put("alarmlist", influxDao.getFlowAlarmData(deviceIdStr));
        returnMap.put("time", DateUtils.getTime());

        return AjaxResult.success(returnMap);
    }

    /**
     * 从数据库中获取数据
     * @param broadbandNO 宽带账号
     * @return 获取的数据
     */
    private JsonArray getDeviceFromDb(String broadbandNO) {
        IFlowDevice flowDeviceSearch = new IFlowDevice();
        flowDeviceSearch.setBroadbandNO(broadbandNO);

        List<IFlowDevice> flowDeviceList = flowDeviceMapper.selectIFlowDeviceList(flowDeviceSearch);

        JsonArray returnJsonArray = new JsonArray();
        for (IFlowDevice flowDevice : flowDeviceList) {
            JsonObject jsonObject = new JsonObject();

            jsonObject.addProperty("deviceId", flowDevice.getDeviceId());
            jsonObject.addProperty("deviceName", flowDevice.getDeviceName());
            jsonObject.addProperty("deviceType", flowDevice.getDeviceType());

            jsonObject.addProperty("chose", 1);

            returnJsonArray.add(jsonObject);
        }
        return returnJsonArray;
    }

    private List<List<String>> translate(List<List<Object>> object2List) {
        List<List<String>> string2List = new ArrayList<>();
        for (List<Object> objectList : object2List) {
            List<String> arrayList = new ArrayList<>();
            String str = (String) objectList.get(0);
            int intValue = Double.valueOf(String.valueOf(objectList.get(1))).intValue();
            arrayList.add(0, str);
            arrayList.add(1, String.valueOf(intValue));
            string2List.add(arrayList);
        }
        return string2List;
    }
}
